
#include <ctype.h>
#include <fcntl.h>
#include <inttypes.h>
#include <getopt.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>

#include <termios.h>
#include <unistd.h>

#include <gui/SurfaceComposerClient.h>
#include "DisplayRecorder.h"
#include "SequenceRecorder.h"
#include "recorder.h"

#include <utils/Log.h>
#include <utils/Errors.h>
#include <binder/IPCThreadState.h>

using android::ProcessState;
using android::NO_ERROR;

SequenceRecorder* mSequenceRecorder;

// -----------命令行相关----------- 

// Previous signal handler state, restored after first hit.
static struct sigaction gOrigSigactionINT;
static struct sigaction gOrigSigactionHUP;

static void signalCatcher(int signum){
    if(mSequenceRecorder != nullptr){
        mSequenceRecorder->stop();
    }
    ALOGD("signalCatcher %d ", signum);
    abort();
}

static status_t configureSignals() {
    struct sigaction act;
    memset(&act, 0, sizeof(act));
    act.sa_handler = signalCatcher;
    if (sigaction(SIGINT, &act, &gOrigSigactionINT) != 0) {
        status_t err = -errno;
        fprintf(stderr, "Unable to configure SIGINT handler: %s\n",
                strerror(errno));
        return err;
    }
    if (sigaction(SIGHUP, &act, &gOrigSigactionHUP) != 0) {
        status_t err = -errno;
        fprintf(stderr, "Unable to configure SIGHUP handler: %s\n",
                strerror(errno));
        return err;
    }
    signal(SIGPIPE, SIG_IGN);
    return NO_ERROR;
}

// -----------命令行相关----------- 

int main(int argc, char* const argv[]) {

    static const struct option longOptions[] = {
        { "time-limit",         required_argument,  NULL, 't' },
        { "display-id",         required_argument,  NULL, 'd' },
        { "loop-recorder",      required_argument,  NULL, 'l' },
        { NULL,                 0,                  NULL, 0 }
    };

    ALOGD("screenrecorder v%d.%d",kVersionMajor, kVersionMinor);
    int duration = 10;
    int loopRecorder = 1;
    std::optional<PhysicalDisplayId> defaultDisplayId = android::SurfaceComposerClient::getInternalDisplayId();
    if (!defaultDisplayId) {
        fprintf(stderr, "Failed to get token for internal display\n");
        return 1;
    }
    PhysicalDisplayId displayId = *defaultDisplayId;
    while (true) {
        int optionIndex = 0;
        int ic = getopt_long(argc, argv, "", longOptions, &optionIndex);
        if (ic == -1) {
            break;
        }
        switch (ic){
        case 't':
            duration = atoi(optarg);
            if (duration == 0) {
               duration = 10;
            }
            break;
        case 'd':
            displayId = atoll(optarg);
            if (displayId == 0) {
                fprintf(stderr, "Please specify a valid physical display id\n");
                return 2;
            } else if (android::SurfaceComposerClient::
                    getPhysicalDisplayToken(displayId) == nullptr) {
                fprintf(stderr, "Invalid physical display id: %"
                        ANDROID_PHYSICAL_DISPLAY_ID_FORMAT "\n", displayId);
                return 2;
            }
            break;
         case 'l':
            loopRecorder = atoi(optarg);
            if (loopRecorder > 0) {
               loopRecorder = 1;
            }
            break;
        default:
            break;
        }
    }

    if (optind != argc - 1) {
        fprintf(stderr, "Must specify output file.\n");
        return 2;
    }

    const char* fileName = argv[optind];
    ALOGD("Parameters %s", fileName);

    status_t err;
     // Configure signal handler.
    err = configureSignals();
    if (err != NO_ERROR) return err;

    if(loopRecorder == 1){
        startLoopRecoder(displayId, fileName, duration);
    } else {
        startRecorder(displayId, fileName, duration);
    }

    return 0;
}

// 开启断点录制
void startLoopRecoder(android::PhysicalDisplayId displayId, const char *rootPath,int duration){
    
    sp<ProcessState> self = ProcessState::self();
    self->startThreadPool();

    auto *sequenceRecorder = new SequenceRecorder(displayId, rootPath, duration);
    sequenceRecorder->start();

    mSequenceRecorder = sequenceRecorder;
}

// 只录制一段
void startRecorder(android::PhysicalDisplayId displayId, const char *rootPath,int duration){
    sp<ProcessState> self = ProcessState::self();
    self->startThreadPool();

    std::string const& path = std::string(rootPath) + std::string("displayer_recorder.mp4");
    auto *displayRecorder = new DisplayRecorder(displayId, path.c_str(), duration);
    displayRecorder->start();
}